package com.example.gateway.filter;

import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import com.example.common.AppVariable;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;

/**
 * @Description: 权限过滤器
 * @Author Mr.Tang
 */


/**
 * 登录过滤器 (登录判断)
 */
@Slf4j
@Component
public class AuthFilter implements GlobalFilter, Ordered {

    // 不需登录验证的 URL 地址
    private String[] skipAuthUrls = {
            "/user/add",
            "/user/login",
            "/user/getByUid",
            "/article/getUserArticle",
            "/article/getListByPage",
            "/article/getById",
            "/comment/listByAid"
    };

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 当前请求的 URL
        String url = exchange.getRequest().getURI().getPath();
        for (String item : skipAuthUrls) {
            if (item.equals(url)) {
                // 继续执行后序的过滤器或业务流程, 继续往下走
                return chain.filter(exchange);
            }
        }

        // 登录判断
        List<String> tokens = exchange.getRequest().getHeaders().get(AppVariable.TOKEN_KEY);
        ServerHttpResponse response = exchange.getResponse();
        if (tokens == null || tokens.size() == 0) {
            // 当前未登录
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }

        // token 有值
        String token = tokens.get(0);
        // JWT 校验 token 值是否有效
        boolean result = false;
        try {
            result = JWTUtil.verify(token, AppVariable.JWT_PRIVATE_KEY.getBytes());
        } catch (Exception e) {
            log.warn("错误的Token!");
        }
        if (!result) {
            // 无效的 token
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }

        // token 有效, 进一步判断 token 是否过期
        JWT jwt = JWTUtil.parseToken(token);
        Object object = jwt.getPayload("exp");
        if (object == null) {
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }

        // 得到过期时间
        long exp = Long.parseLong(object.toString());
        if (System.currentTimeMillis() > exp) {
            // token 已过期
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }

        // token 成功验证, 将jwt里面的 uid, manager 存到 header 里
        String uid = jwt.getPayload("uid").toString();
        String manager = jwt.getPayload("manager").toString();
        response.getHeaders().set("uid", uid);
        response.getHeaders().set("manager", manager);
        // 修改原始 request 添加 header
        ServerHttpRequest request = exchange.getRequest().mutate()
                .header("uid", uid)
                .header("manager", manager).build();

        // 带着修改过的request往下走
        return chain.filter(exchange.mutate().request(request).build());
    }

    @Override
    public int getOrder() {
        // 值越小越早执行
        return 1;
    }
}
